#ifndef DOUBLEBUFFER_INCLUDE
#define DOUBLEBUFFER_INCLUDE

#include <atomic>
#include <string>

template<class T>
class DoubleBuffer
{
public:
    // typedef T* iterator;
	// typedef const T* const_iterator;

    DoubleBuffer() {
        data_ptr[0] = new T;
        data_ptr[1] = new T;
        usingData = 0;
        getData = 0;
        busy = 0;
    }
    ~DoubleBuffer() {
        delete data_ptr[0];
        delete data_ptr[1];
        getData = 0;
        busy = 1;
    }

    T ReadBuffer() {
        if (!getData)
            return T();
        while(1)
        {
            if(busy)
                continue;
            busy = 1;
            T middle_data = *data_ptr[usingData];
            busy = 0;
            return middle_data;
        }
    }
    void WriterBuffer(T data) {
        if(usingData == 0)
            *data_ptr[1] = data;
        else
            *data_ptr[0] = data;
        while(1)
        {
            if(busy)
                continue;
            busy = 1;
            if(usingData == 0)
                usingData = 1;
            else   
                usingData = 0;
            busy = 0;
            getData = 1;
            return;
        }
    }

    void operator>>(T &data) { data = ReadBuffer(); }
    void operator<<(T data) { WriterBuffer(data); }
private:
    T* data_ptr[2];
    int usingData;
    std::atomic<bool> getData;
    std::atomic<bool> busy;
};

#endif